using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Threading;

namespace Common.ThreadSyscClass
{
	[Serializable]
	public class AsyncObservableCollection<T> : ObservableCollection<T>
	{
		[NonSerialized]
		private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;

		public AsyncObservableCollection()
		{
		}

		public AsyncObservableCollection(IList<T> list)
			: base((IEnumerable<T>)list)
		{
		}

		protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
		{
			if (SynchronizationContext.Current == _synchronizationContext)
			{
				RaiseCollectionChanged(e);
			}
			else if (_synchronizationContext != null)
			{
				_synchronizationContext.Send(RaiseCollectionChanged, e);
			}
		}

		private void RaiseCollectionChanged(object param)
		{
			base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
		}

		protected override void OnPropertyChanged(PropertyChangedEventArgs e)
		{
			if (SynchronizationContext.Current == _synchronizationContext)
			{
				RaisePropertyChanged(e);
			}
			else if (_synchronizationContext != null)
			{
				_synchronizationContext.Send(RaisePropertyChanged, e);
			}
		}

		private void RaisePropertyChanged(object param)
		{
			base.OnPropertyChanged((PropertyChangedEventArgs)param);
		}

		[OnDeserialized]
		private void OnDeserialized(StreamingContext context)
		{
			_synchronizationContext = SynchronizationContext.Current;
		}
	}
}
